home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / libpng / pngwutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-13  |  56.8 KB  |  1,918 lines

  1.  
  2. /* pngwutil.c - utilities to write a PNG file
  3.  
  4.    libpng 1.0 beta 6 - version 0.96
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  7.    Copyright (c) 1996, 1997 Andreas Dilger
  8.    May 12, 1997
  9.    */
  10.  
  11. #define PNG_INTERNAL
  12. #include "png.h"
  13.  
  14. /* Place a 32-bit number into a buffer in PNG byte order.  We work
  15.  * with unsigned numbers for convenience, although one supported
  16.  * ancillary chunk uses signed (two's complement) numbers.
  17.  */
  18. void
  19. png_save_uint_32(png_bytep buf, png_uint_32 i)
  20. {
  21.    buf[0] = (png_byte)((i >> 24) & 0xff);
  22.    buf[1] = (png_byte)((i >> 16) & 0xff);
  23.    buf[2] = (png_byte)((i >> 8) & 0xff);
  24.    buf[3] = (png_byte)(i & 0xff);
  25. }
  26.  
  27. #if defined(PNG_WRITE_pCAL_SUPPORTED)
  28. /* The png_save_int_32 function assumes integers are stored in two's
  29.    complement format.  If this isn't the case, then this routine needs to
  30.    be modified to write data in two's complement format. */
  31. void
  32. png_save_int_32(png_bytep buf, png_int_32 i)
  33. {
  34.    buf[0] = (png_byte)((i >> 24) & 0xff);
  35.    buf[1] = (png_byte)((i >> 16) & 0xff);
  36.    buf[2] = (png_byte)((i >> 8) & 0xff);
  37.    buf[3] = (png_byte)(i & 0xff);
  38. }
  39. #endif
  40.  
  41. /* Place a 16-bit number into a buffer in PNG byte order. */
  42. void
  43. png_save_uint_16(png_bytep buf, png_uint_16 i)
  44. {
  45.    buf[0] = (png_byte)((i >> 8) & 0xff);
  46.    buf[1] = (png_byte)(i & 0xff);
  47. }
  48.  
  49. /* Write a PNG chunk all at once.  The type is an array of ASCII characters
  50.    representing the chunk name.  The array must be at least 4 bytes in
  51.    length, and does not need to be null terminated.  To be safe, pass the
  52.    pre-defined chunk names here, and if you need a new one, define it
  53.    where the others are defined.  The length is the length of the data.
  54.    All the data must be present.  If that is not possible, use the
  55.    png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
  56.    functions instead.  */
  57. void
  58. png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
  59.    png_bytep data, png_size_t length)
  60. {
  61.    png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
  62.    png_write_chunk_data(png_ptr, data, length);
  63.    png_write_chunk_end(png_ptr);
  64. }
  65.  
  66. /* Write the start of a PNG chunk.  The type is the chunk type.
  67.    The total_length is the sum of the lengths of all the data you will be
  68.    passing in png_write_chunk_data() */
  69. void
  70. png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
  71.    png_uint_32 length)
  72. {
  73.    png_byte buf[4];
  74.    png_debug2(0, "Writing %s chunk (%d bytes)\n", chunk_name, length);
  75.  
  76.    /* write the length */
  77.    png_save_uint_32(buf, length);
  78.    png_write_data(png_ptr, buf, (png_size_t)4);
  79.  
  80.    /* write the chunk name */
  81.    png_write_data(png_ptr, chunk_name, (png_size_t)4);
  82.    /* reset the crc and run it over the chunk name */
  83.    png_reset_crc(png_ptr);
  84.    png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
  85. }
  86.  
  87. /* Write the data of a PNG chunk started with png_write_chunk_start().
  88.    Note that multiple calls to this function are allowed, and that the
  89.    sum of the lengths from these calls *must* add up to the total_length
  90.    given to png_write_chunk_start(). */
  91. void
  92. png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
  93. {
  94.    /* write the data, and run the CRC over it */
  95.    if (data != NULL && length > 0)
  96.    {
  97.       png_calculate_crc(png_ptr, data, length);
  98.       png_write_data(png_ptr, data, length);
  99.    }
  100. }
  101.  
  102. /* Finish a chunk started with png_write_chunk_start(). */
  103. void
  104. png_write_chunk_end(png_structp png_ptr)
  105. {
  106.    png_byte buf[4];
  107.  
  108.    /* write the crc */
  109. #ifdef PNG_USE_OWN_CRC
  110.    png_save_uint_32(buf, ~png_ptr->crc);
  111. #else
  112.    png_save_uint_32(buf, png_ptr->crc);
  113. #endif
  114.  
  115.    png_write_data(png_ptr, buf, (png_size_t)4);
  116. }
  117.  
  118. /* Simple function to write the signature.  If we have already written
  119.  * the magic bytes of the signature, or more likely, the PNG stream is
  120.  * being embedded into another stream and doesn't need its own signature,
  121.  * we should call png_set_sig_bytes() to tell libpng how many of the
  122.  * bytes have already been written. */
  123. void
  124. png_write_sig(png_structp png_ptr)
  125. {
  126.    /* write the rest of the 8 byte signature */
  127.    png_write_data(png_ptr, &png_sig[png_ptr->sig_bytes],
  128.       (png_size_t)8 - png_ptr->sig_bytes);
  129. }
  130.  
  131. /* Write the IHDR chunk, and update the png_struct with the necessary
  132.    information.  Note that the rest of this code depends upon this
  133.    information being correct.  */
  134. void
  135. png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
  136.    int bit_depth, int color_type, int compression_type, int filter_type,
  137.    int interlace_type)
  138. {
  139.    png_byte buf[13]; /* buffer to store the IHDR info */
  140.  
  141.    png_debug(1, "in png_write_IHDR\n");
  142.    /* Check that we have valid input data from the application info */
  143.    switch (color_type)
  144.    {
  145.       case PNG_COLOR_TYPE_GRAY:
  146.          switch (bit_depth)
  147.          {
  148.             case 1:
  149.             case 2:
  150.             case 4:
  151.             case 8:
  152.             case 16: png_ptr->channels = 1; break;
  153.             default: png_error(png_ptr,"Invalid bit depth for grayscale image");
  154.          }
  155.          break;
  156.       case PNG_COLOR_TYPE_RGB:
  157.          if (bit_depth != 8 && bit_depth != 16)
  158.             png_error(png_ptr, "Invalid bit depth for RGB image");
  159.          png_ptr->channels = 3;
  160.          break;
  161.       case PNG_COLOR_TYPE_PALETTE:
  162.          switch (bit_depth)
  163.          {
  164.             case 1:
  165.             case 2:
  166.             case 4:
  167.             case 8: png_ptr->channels = 1; break;
  168.             default: png_error(png_ptr, "Invalid bit depth for paletted image");
  169.          }
  170.          break;
  171.       case PNG_COLOR_TYPE_GRAY_ALPHA:
  172.          if (bit_depth != 8 && bit_depth != 16)
  173.             png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
  174.          png_ptr->channels = 2;
  175.          break;
  176.       case PNG_COLOR_TYPE_RGB_ALPHA:
  177.          if (bit_depth != 8 && bit_depth != 16)
  178.             png_error(png_ptr, "Invalid bit depth for RGBA image");
  179.          png_ptr->channels = 4;
  180.          break;
  181.       default:
  182.          png_error(png_ptr, "Invalid image color type specified");
  183.    }
  184.  
  185.    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
  186.    {
  187.       png_warning(png_ptr, "Invalid compression type specified");
  188.       compression_type = PNG_COMPRESSION_TYPE_BASE;
  189.    }
  190.  
  191.    if (filter_type != PNG_FILTER_TYPE_BASE)
  192.    {
  193.       png_warning(png_ptr, "Invalid filter type specified");
  194.       filter_type = PNG_FILTER_TYPE_BASE;
  195.    }
  196.  
  197.    if (interlace_type != PNG_INTERLACE_NONE &&
  198.       interlace_type != PNG_INTERLACE_ADAM7)
  199.    {
  200.       png_warning(png_ptr, "Invalid interlace type specified");
  201.       interlace_type = PNG_INTERLACE_ADAM7;
  202.    }
  203.  
  204.    /* save off the relevent information */
  205.    png_ptr->bit_depth = (png_byte)bit_depth;
  206.    png_ptr->color_type = (png_byte)color_type;
  207.    png_ptr->interlaced = (png_byte)interlace_type;
  208.    png_ptr->width = width;
  209.    png_ptr->height = height;
  210.  
  211.    png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
  212.    png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3);
  213.    /* set the usr info, so any transformations can modify it */
  214.    png_ptr->usr_width = png_ptr->width;
  215.    png_ptr->usr_bit_depth = png_ptr->bit_depth;
  216.    png_ptr->usr_channels = png_ptr->channels;
  217.  
  218.    /* pack the header information into the buffer */
  219.    png_save_uint_32(buf, width);
  220.    png_save_uint_32(buf + 4, height);
  221.    buf[8] = (png_byte)bit_depth;
  222.    buf[9] = (png_byte)color_type;
  223.    buf[10] = (png_byte)compression_type;
  224.    buf[11] = (png_byte)filter_type;
  225.    buf[12] = (png_byte)interlace_type;
  226.  
  227.    /* write the chunk */
  228.    png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
  229.  
  230.    /* initialize zlib with PNG info */
  231.    png_ptr->zstream.zalloc = png_zalloc;
  232.    png_ptr->zstream.zfree = png_zfree;
  233.    png_ptr->zstream.opaque = (voidpf)png_ptr;
  234.    if (!(png_ptr->do_filter))
  235.    {
  236.       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
  237.          png_ptr->bit_depth < 8)
  238.          png_ptr->do_filter = PNG_FILTER_NONE;
  239.       else
  240.          png_ptr->do_filter = PNG_ALL_FILTERS;
  241.    }
  242.    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
  243.    {
  244.       if (png_ptr->do_filter != PNG_FILTER_NONE)
  245.          png_ptr->zlib_strategy = Z_FILTERED;
  246.       else
  247.          png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
  248.    }
  249.    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
  250.       png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
  251.    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
  252.       png_ptr->zlib_mem_level = 8;
  253.    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
  254.       png_ptr->zlib_window_bits = 15;
  255.    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
  256.       png_ptr->zlib_method = 8;
  257.    deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
  258.       png_ptr->zlib_method, png_ptr->zlib_window_bits,
  259.       png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
  260.    png_ptr->zstream.next_out = png_ptr->zbuf;
  261.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  262.  
  263.    png_ptr->mode = PNG_HAVE_IHDR;
  264. }
  265.  
  266. /* write the palette.  We are careful not to trust png_color to be in the
  267.    correct order for PNG, so people can redefine it to any convient
  268.    structure. */
  269. void
  270. png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
  271. {
  272.    png_uint_32 i;
  273.    png_colorp pal_ptr;
  274.    png_byte buf[3];
  275.  
  276.    png_debug(1, "in png_write_PLTE\n");
  277.    if (num_pal == 0 || num_pal > 256)
  278.    {
  279.       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  280.       {
  281.          png_error(png_ptr, "Invalid number of colors in palette");
  282.       }
  283.       else
  284.       {
  285.          png_warning(png_ptr, "Invalid number of colors in palette");
  286.          return;
  287.       }
  288.    }
  289.  
  290.    png_ptr->num_palette = (png_uint_16)num_pal;
  291.    png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
  292.  
  293.    png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3);
  294.    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
  295.    {
  296.       buf[0] = pal_ptr->red;
  297.       buf[1] = pal_ptr->green;
  298.       buf[2] = pal_ptr->blue;
  299.       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
  300.    }
  301.    png_write_chunk_end(png_ptr);
  302.    png_ptr->mode |= PNG_HAVE_PLTE;
  303. }
  304.  
  305. /* write an IDAT chunk */
  306. void
  307. png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
  308. {
  309.    png_debug(1, "in png_write_IDAT\n");
  310.    png_write_chunk(png_ptr, png_IDAT, data, length);
  311.    png_ptr->mode |= PNG_HAVE_IDAT;
  312. }
  313.  
  314. /* write an IEND chunk */
  315. void
  316. png_write_IEND(png_structp png_ptr)
  317. {
  318.    png_debug(1, "in png_write_IEND\n");
  319.    png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
  320.    png_ptr->mode |= PNG_HAVE_IEND;
  321. }
  322.  
  323. #if defined(PNG_WRITE_gAMA_SUPPORTED)
  324. /* write a gAMA chunk */
  325. void
  326. png_write_gAMA(png_structp png_ptr, double file_gamma)
  327. {
  328.    png_uint_32 igamma;
  329.    png_byte buf[4];
  330.  
  331.    png_debug(1, "in png_write_gAMA\n");
  332.    /* file_gamma is saved in 1/100,000ths */
  333.    igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
  334.    png_save_uint_32(buf, igamma);
  335.    png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
  336. }
  337. #endif
  338.  
  339. #if defined(PNG_WRITE_sBIT_SUPPORTED)
  340. /* write the sBIT chunk */
  341. void
  342. png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
  343. {
  344.    png_byte buf[4];
  345.    png_size_t size;
  346.  
  347.    png_debug(1, "in png_write_sBIT\n");
  348.    /* make sure we don't depend upon the order of PNG_COLOR_8 */
  349.    if (color_type & PNG_COLOR_MASK_COLOR)
  350.    {
  351.       int maxbits;
  352.  
  353.       maxbits = color_type==PNG_COLOR_TYPE_PALETTE ? 8:png_ptr->usr_bit_depth;
  354.       if (sbit->red == 0 || sbit->red > maxbits || 
  355.           sbit->green == 0 || sbit->green > maxbits || 
  356.           sbit->blue == 0 || sbit->blue > maxbits)
  357.       {
  358.          png_warning(png_ptr, "Invalid sBIT depth specified");
  359.          return;
  360.       }
  361.       buf[0] = sbit->red;
  362.       buf[1] = sbit->green;
  363.       buf[2] = sbit->blue;
  364.       size = 3;
  365.    }
  366.    else
  367.    {
  368.       if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
  369.       {
  370.          png_warning(png_ptr, "Invalid sBIT depth specified");
  371.          return;
  372.       }
  373.       buf[0] = sbit->gray;
  374.       size = 1;
  375.    }
  376.  
  377.    if (color_type & PNG_COLOR_MASK_ALPHA)
  378.    {
  379.       if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
  380.       {
  381.          png_warning(png_ptr, "Invalid sBIT depth specified");
  382.          return;
  383.       }
  384.       buf[size++] = sbit->alpha;
  385.    }
  386.  
  387.    png_write_chunk(png_ptr, png_sBIT, buf, size);
  388. }
  389. #endif
  390.  
  391. #if defined(PNG_WRITE_cHRM_SUPPORTED)
  392. /* write the cHRM chunk */
  393. void
  394. png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
  395.    double red_x, double red_y, double green_x, double green_y,
  396.    double blue_x, double blue_y)
  397. {
  398.    png_uint_32 itemp;
  399.    png_byte buf[32];
  400.  
  401.    png_debug(1, "in png_write_cHRM\n");
  402.    /* each value is saved int 1/100,000ths */
  403.    if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
  404.        white_x + white_y > 1.0)
  405.    {
  406.       png_warning(png_ptr, "Invalid cHRM white point specified");
  407.       return;
  408.    }
  409.    itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
  410.    png_save_uint_32(buf, itemp);
  411.    itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
  412.    png_save_uint_32(buf + 4, itemp);
  413.  
  414.    if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
  415.        red_x + red_y > 1.0)
  416.    {
  417.       png_warning(png_ptr, "Invalid cHRM red point specified");
  418.       return;
  419.    }
  420.    itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
  421.    png_save_uint_32(buf + 8, itemp);
  422.    itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
  423.    png_save_uint_32(buf + 12, itemp);
  424.  
  425.    if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
  426.        green_x + green_y > 1.0)
  427.    {
  428.       png_warning(png_ptr, "Invalid cHRM green point specified");
  429.       return;
  430.    }
  431.    itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
  432.    png_save_uint_32(buf + 16, itemp);
  433.    itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
  434.    png_save_uint_32(buf + 20, itemp);
  435.  
  436.    if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
  437.        blue_x + blue_y > 1.0)
  438.    {
  439.       png_warning(png_ptr, "Invalid cHRM blue point specified");
  440.       return;
  441.    }
  442.    itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
  443.    png_save_uint_32(buf + 24, itemp);
  444.    itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
  445.    png_save_uint_32(buf + 28, itemp);
  446.  
  447.    png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
  448. }
  449. #endif
  450.  
  451. #if defined(PNG_WRITE_tRNS_SUPPORTED)
  452. /* write the tRNS chunk */
  453. void
  454. png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
  455.    int num_trans, int color_type)
  456. {
  457.    png_byte buf[6];
  458.  
  459.    png_debug(1, "in png_write_tRNS\n");
  460.    if (color_type == PNG_COLOR_TYPE_PALETTE)
  461.    {
  462.       if (num_trans <= 0 || num_trans > png_ptr->num_palette)
  463.       {
  464.          png_warning(png_ptr,"Invalid number of transparent colors specified");
  465.          return;
  466.       }
  467.       /* write the chunk out as it is */
  468.       png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans);
  469.    }
  470.    else if (color_type == PNG_COLOR_TYPE_GRAY)
  471.    {
  472.       /* one 16 bit value */
  473.       png_save_uint_16(buf, tran->gray);
  474.       png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
  475.    }
  476.    else if (color_type == PNG_COLOR_TYPE_RGB)
  477.    {
  478.       /* three 16 bit values */
  479.       png_save_uint_16(buf, tran->red);
  480.       png_save_uint_16(buf + 2, tran->green);
  481.       png_save_uint_16(buf + 4, tran->blue);
  482.       png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
  483.    }
  484.    else
  485.    {
  486.       png_warning(png_ptr, "Can't write tRNS with and alpha channel");
  487.    }
  488. }
  489. #endif
  490.  
  491. #if defined(PNG_WRITE_bKGD_SUPPORTED)
  492. /* write the background chunk */
  493. void
  494. png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
  495. {
  496.    png_byte buf[6];
  497.  
  498.    png_debug(1, "in png_write_bKGD\n");
  499.    if (color_type == PNG_COLOR_TYPE_PALETTE)
  500.    {
  501.       if (back->index > png_ptr->num_palette)
  502.       {
  503.          png_warning(png_ptr, "Invalid background palette index");
  504.          return;
  505.       }
  506.       buf[0] = back->index;
  507.       png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
  508.    }
  509.    else if (color_type & PNG_COLOR_MASK_COLOR)
  510.    {
  511.       png_save_uint_16(buf, back->red);
  512.       png_save_uint_16(buf + 2, back->green);
  513.       png_save_uint_16(buf + 4, back->blue);
  514.       png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
  515.    }
  516.    else
  517.    {
  518.       png_save_uint_16(buf, back->gray);
  519.       png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
  520.    }
  521. }
  522. #endif
  523.  
  524. #if defined(PNG_WRITE_hIST_SUPPORTED)
  525. /* write the histogram */
  526. void
  527. png_write_hIST(png_structp png_ptr, png_uint_16p hist, png_uint_32 num_hist)
  528. {
  529.    png_uint_32 i;
  530.    png_byte buf[3];
  531.  
  532.    png_debug(1, "in png_write_hIST\n");
  533.    if (num_hist > png_ptr->num_palette)
  534.    {
  535.       png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
  536.          png_ptr->num_palette);
  537.       png_warning(png_ptr, "Invalid number of histogram entries specified");
  538.       return;
  539.    }
  540.  
  541.    png_write_chunk_start(png_ptr, png_hIST, num_hist * 2);
  542.    for (i = 0; i < num_hist; i++)
  543.    {
  544.       png_save_uint_16(buf, hist[i]);
  545.       png_write_chunk_data(png_ptr, buf, (png_size_t)2);
  546.    }
  547.    png_write_chunk_end(png_ptr);
  548. }
  549. #endif
  550.  
  551. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  552. /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
  553.  * and if invalid, correct the keyword rather than discarding the entire
  554.  * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
  555.  * length, forbids leading or trailing whitespace, multiple internal spaces,
  556.  * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
  557.  *
  558.  * The new_key is allocated to hold the corrected keyword and must be freed
  559.  * by the calling routine.  This avoids problems with trying to write to
  560.  * static keywords without having to have duplicate copies of the strings.
  561.  */
  562. png_size_t
  563. png_check_keyword(png_structp png_ptr, png_charp key, png_bytepp new_key)
  564. {
  565.    png_size_t key_len;
  566.    png_charp kp;
  567.    png_bytep dp;
  568.    int kflag;
  569.  
  570.    png_debug(1, "in png_check_keyword\n");
  571.    *new_key = NULL;
  572.  
  573.    if (key == NULL || (key_len = png_strlen(key)) == 0)
  574.    {
  575.       char msg[40];
  576.  
  577.       sprintf(msg, "Zero length %s keyword", png_ptr->chunk_name);
  578.       png_warning(png_ptr, msg);
  579.       return 0;
  580.    }
  581.  
  582.    png_debug1(2, "Keyword to be checked is '%s'\n", key);
  583.  
  584.    *new_key = (png_bytep)png_malloc(png_ptr, key_len + 1);
  585.  
  586.    /* Replace non-printing characters with a blank and print a warning */
  587.    for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
  588.    {
  589.       if (*kp < 0x20 || ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
  590.       {
  591.          char msg[40];
  592.  
  593.          sprintf(msg, "Invalid %s keyword character 0x%02X",
  594.             png_ptr->chunk_name, *kp);
  595.          png_warning(png_ptr, msg);
  596.          *dp = ' ';
  597.       }
  598.       else
  599.       {
  600.          *dp = *kp;
  601.       }
  602.    }
  603.    *dp = '\0';
  604.  
  605.    /* Remove any trailing white space. */
  606.    kp = *new_key + key_len - 1;
  607.    if (*kp == ' ')
  608.    {
  609.       char msg[50];
  610.       sprintf(msg, "Trailing spaces removed from %s keyword",
  611.          png_ptr->chunk_name);
  612.  
  613.       png_warning(png_ptr, msg);
  614.  
  615.       while (*kp == ' ')
  616.       {
  617.         *(kp--) = '\0';
  618.         key_len--;
  619.       }
  620.    }
  621.  
  622.    /* Remove any leading white space. */
  623.    kp = *new_key;
  624.    if (*kp == ' ')
  625.    {
  626.       char msg[50];
  627.       sprintf(msg, "Leading spaces removed from %s keyword",
  628.          png_ptr->chunk_name);
  629.  
  630.       png_warning(png_ptr, msg);
  631.  
  632.       while (*kp == ' ')
  633.       {
  634.         kp++;
  635.         key_len--;
  636.       }
  637.    }
  638.  
  639.    png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
  640.  
  641.    /* Remove multiple internal spaces. */
  642.    for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
  643.    {
  644.       if (*kp == ' ' && kflag == 0)
  645.       {
  646.          *(dp++) = *kp;
  647.          kflag = 1;
  648.       }
  649.       else if (*kp == ' ')
  650.       {
  651.          key_len--;
  652.       }
  653.       else
  654.       {
  655.          *(dp++) = *kp;
  656.          kflag = 0;
  657.       }
  658.    }
  659.    *dp = '\0';
  660.  
  661.    if (key_len == 0)
  662.    {
  663.       char msg[40];
  664.  
  665.       sprintf(msg, "Zero length %s keyword", png_ptr->chunk_name);
  666.       png_warning(png_ptr, msg);
  667.    }
  668.  
  669.    if (key_len > 79)
  670.    {
  671.       char msg[50];
  672.  
  673.       sprintf(msg, "%s keyword length must be 1 - 79 characters",
  674.          png_ptr->chunk_name);
  675.       png_warning(png_ptr, msg);
  676.       new_key[79] = '\0';
  677.       key_len = 79;
  678.    }
  679.  
  680.    return key_len;
  681. }
  682. #endif
  683.  
  684. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  685. /* write a tEXt chunk */
  686. void
  687. png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
  688.    png_size_t text_len)
  689. {
  690.    png_size_t key_len;
  691.    png_bytep new_key;
  692.  
  693.    png_debug(1, "in png_write_tEXt\n");
  694.    if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
  695.    {
  696.       char msg[40];
  697.  
  698.       sprintf(msg, "Empty keyword in %s chunk", "tEXt");
  699.       png_warning(png_ptr, msg);
  700.       return;
  701.    }
  702.  
  703.    if (text == NULL || *text == '\0')
  704.       text_len = 0;
  705.  
  706.    /* make sure we include the 0 after the key */
  707.    png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1);
  708.    png_write_chunk_data(png_ptr, new_key, key_len + 1);
  709.    if (text_len)
  710.       png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
  711.  
  712.    png_write_chunk_end(png_ptr);
  713.    png_free(png_ptr, new_key);
  714. }
  715. #endif
  716.  
  717. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  718. /* write a compressed text chunk */
  719. void
  720. png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
  721.    png_size_t text_len, int compression)
  722. {
  723.    png_size_t key_len;
  724.    char buf[1];
  725.    png_bytep new_key;
  726.    int i, ret;
  727.    png_charpp output_ptr = NULL; /* array of pointers to output */
  728.    int num_output_ptr = 0; /* number of output pointers used */
  729.    int max_output_ptr = 0; /* size of output_ptr */
  730.  
  731.    png_debug(1, "in png_write_zTXt\n");
  732.  
  733.    if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
  734.    {
  735.       char msg[40];
  736.  
  737.       sprintf(msg, "Empty keyword in %s chunk", "zTXt");
  738.       png_warning(png_ptr, msg);
  739.       return;
  740.    }
  741.  
  742.    if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
  743.    {
  744.       png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
  745.       png_free(png_ptr, new_key);
  746.       return;
  747.    }
  748.  
  749.    png_free(png_ptr, new_key);
  750.  
  751.    if (compression >= PNG_TEXT_COMPRESSION_LAST)
  752.    {
  753.       char msg[50];
  754.       sprintf(msg, "Unknown zTXt compression type %d", compression);
  755.       png_warning(png_ptr, msg);
  756.       compression = PNG_TEXT_COMPRESSION_zTXt;
  757.    }
  758.  
  759.    /* We can't write the chunk until we find out how much data we have,
  760.     * which means we need to run the compressor first, and save the
  761.     * output.  This shouldn't be a problem, as the vast majority of
  762.     * comments should be reasonable, but we will set up an array of
  763.     * malloc'd pointers to be sure.
  764.     *
  765.     * If we knew the application was well behaved, we could simplify this
  766.     * greatly by assuming we can always malloc an output buffer large
  767.     * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
  768.     * and malloc this directly.  The only time this would be a bad idea is
  769.     * if we can't malloc more than 64K and we have 64K of random input
  770.     * data, or if the input string is incredibly large (although this
  771.     * wouldn't cause a failure, just a slowdown due to swapping).
  772.     */
  773.  
  774.    /* set up the compression buffers */
  775.    png_ptr->zstream.avail_in = (uInt)text_len;
  776.    png_ptr->zstream.next_in = (Bytef *)text;
  777.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  778.    png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
  779.  
  780.    /* this is the same compression loop as in png_write_row() */
  781.    do
  782.    {
  783.       /* compress the data */
  784.       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
  785.       if (ret != Z_OK)
  786.       {
  787.          /* error */
  788.          if (png_ptr->zstream.msg != NULL)
  789.             png_error(png_ptr, png_ptr->zstream.msg);
  790.          else
  791.             png_error(png_ptr, "zlib error");
  792.       }
  793.       /* check to see if we need more room */
  794.       if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in)
  795.       {
  796.          /* make sure the output array has room */
  797.          if (num_output_ptr >= max_output_ptr)
  798.          {
  799.             int old_max;
  800.  
  801.             old_max = max_output_ptr;
  802.             max_output_ptr = num_output_ptr + 4;
  803.             if (output_ptr != NULL)
  804.             {
  805.                png_charpp old_ptr;
  806.  
  807.                old_ptr = output_ptr;
  808.                output_ptr = (png_charpp)png_malloc(png_ptr,
  809.                   max_output_ptr * sizeof (png_charpp));
  810.                png_memcpy(output_ptr, old_ptr, old_max * sizeof (png_charp));
  811.                png_free(png_ptr, old_ptr);
  812.             }
  813.             else
  814.                output_ptr = (png_charpp)png_malloc(png_ptr,
  815.                   max_output_ptr * sizeof (png_charp));
  816.          }
  817.  
  818.          /* save the data */
  819.          output_ptr[num_output_ptr] = png_malloc(png_ptr, png_ptr->zbuf_size);
  820.          png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf,
  821.             png_ptr->zbuf_size);
  822.          num_output_ptr++;
  823.  
  824.          /* and reset the buffer */
  825.          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  826.          png_ptr->zstream.next_out = png_ptr->zbuf;
  827.       }
  828.    /* continue until we don't have anymore to compress */
  829.    } while (png_ptr->zstream.avail_in);
  830.  
  831.    /* finish the compression */
  832.    do
  833.    {
  834.       /* tell zlib we are finished */
  835.       ret = deflate(&png_ptr->zstream, Z_FINISH);
  836.       if (ret != Z_OK && ret != Z_STREAM_END)
  837.       {
  838.          /* we got an error */
  839.          if (png_ptr->zstream.msg != NULL)
  840.             png_error(png_ptr, png_ptr->zstream.msg);
  841.          else
  842.             png_error(png_ptr, "zlib error");
  843.       }
  844.  
  845.       /* check to see if we need more room */
  846.       if (!(png_ptr->zstream.avail_out) && ret == Z_OK)
  847.       {
  848.          /* check to make sure our output array has room */
  849.          if (num_output_ptr >= max_output_ptr)
  850.          {
  851.             int old_max;
  852.  
  853.             old_max = max_output_ptr;
  854.             max_output_ptr = num_output_ptr + 4;
  855.             if (output_ptr != NULL)
  856.             {
  857.                png_charpp old_ptr;
  858.  
  859.                old_ptr = output_ptr;
  860.                /* This could be optimized to realloc() */
  861.                output_ptr = (png_charpp)png_malloc(png_ptr,
  862.                   max_output_ptr * sizeof (png_charpp));
  863.                png_memcpy(output_ptr, old_ptr, old_max * sizeof (png_charp));
  864.                png_free(png_ptr, old_ptr);
  865.             }
  866.             else
  867.                output_ptr = (png_charpp)png_malloc(png_ptr,
  868.                   max_output_ptr * sizeof (png_charp));
  869.          }
  870.  
  871.          /* save off the data */
  872.          output_ptr[num_output_ptr] = png_malloc(png_ptr,
  873.             png_ptr->zbuf_size);
  874.          png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf,
  875.             png_ptr->zbuf_size);
  876.          num_output_ptr++;
  877.  
  878.          /* and reset the buffer pointers */
  879.          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  880.          png_ptr->zstream.next_out = png_ptr->zbuf;
  881.       }
  882.    } while (ret != Z_STREAM_END);
  883.  
  884.    /* text length is number of buffers plus last buffer */
  885.    text_len = png_ptr->zbuf_size * num_output_ptr;
  886.    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
  887.       text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
  888.  
  889.    /* write start of chunk */
  890.    png_write_chunk_start(png_ptr, png_zTXt, (png_uint_32)(key_len+text_len+2));
  891.    /* write key */
  892.    png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1);
  893.    buf[0] = (png_byte)compression;
  894.    /* write compression */
  895.    png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
  896.  
  897.    /* write saved output buffers, if any */
  898.    for (i = 0; i < num_output_ptr; i++)
  899.    {
  900.       png_write_chunk_data(png_ptr,(png_bytep)output_ptr[i],png_ptr->zbuf_size);
  901.       png_free(png_ptr, output_ptr[i]);
  902.    }
  903.    if (max_output_ptr != 0)
  904.       png_free(png_ptr, output_ptr);
  905.    /* write anything left in zbuf */
  906.    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
  907.       png_write_chunk_data(png_ptr, png_ptr->zbuf,
  908.          png_ptr->zbuf_size - png_ptr->zstream.avail_out);
  909.    /* close the chunk */
  910.    png_write_chunk_end(png_ptr);
  911.  
  912.    /* reset zlib for another zTXt or the image data */
  913.    deflateReset(&png_ptr->zstream);
  914. }
  915. #endif
  916.  
  917.  
  918. #if defined(PNG_WRITE_oFFs_SUPPORTED)
  919. /* write the oFFs chunk */
  920. void
  921. png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset,
  922.    png_uint_32 y_offset,
  923.    int unit_type)
  924. {
  925.    png_byte buf[9];
  926.  
  927.    png_debug(1, "in png_write_oFFs\n");
  928.    if (unit_type >= PNG_OFFSET_LAST)
  929.       png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
  930.  
  931.    png_save_uint_32(buf, x_offset);
  932.    png_save_uint_32(buf + 4, y_offset);
  933.    buf[8] = (png_byte)unit_type;
  934.  
  935.    png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
  936. }
  937. #endif
  938.  
  939. #if defined(PNG_WRITE_pCAL_SUPPORTED)
  940. /* write the pCAL chunk (png-scivis-19970203) */
  941. void
  942. png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
  943.    png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
  944. {
  945.    png_size_t purpose_len, units_len, total_len; 
  946.    png_uint_32p params_len;
  947.    png_byte buf[10];
  948.    png_bytep new_purpose;
  949.    int i;
  950.  
  951.    png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
  952.    if (type >= PNG_EQUATION_LAST)
  953.       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
  954.  
  955.    purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
  956.    png_debug1(3, "pCAL purpose length = %d\n", purpose_len);
  957.    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
  958.    png_debug1(3, "pCAL units length = %d\n", units_len);
  959.    total_len = purpose_len + units_len + 10;
  960.  
  961.    params_len = (png_uint_32p)png_malloc(png_ptr, nparams*sizeof(png_uint_32));
  962.  
  963.    /* Find the length of each parameter, making sure we don't count the
  964.       null terminator for the last parameter. */
  965.    for (i = 0; i < nparams; i++)
  966.    {
  967.       params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
  968.       png_debug2(3, "pCAL parameter %d length = %d\n", i, params_len[i]);
  969.       total_len += (png_size_t)params_len[i];
  970.    }
  971.  
  972.    png_debug1(3, "pCAL total length = %d\n", total_len);
  973.    png_write_chunk_start(png_ptr, png_pCAL, total_len);
  974.    png_write_chunk_data(png_ptr, new_purpose, purpose_len);
  975.    png_save_int_32(buf, X0);
  976.    png_save_int_32(buf + 4, X1);
  977.    buf[8] = (png_byte)type;
  978.    buf[9] = (png_byte)nparams;
  979.    png_write_chunk_data(png_ptr, buf, (png_size_t)10);
  980.    png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
  981.  
  982.    png_free(png_ptr, new_purpose);
  983.  
  984.    for (i = 0; i < nparams; i++)
  985.    {
  986.       png_write_chunk_data(png_ptr, (png_bytep)params[i],
  987.          (png_size_t)params_len[i]);
  988.    }
  989.  
  990.    png_write_chunk_end(png_ptr);
  991. }
  992. #endif
  993.  
  994. #if defined(PNG_WRITE_pHYs_SUPPORTED)
  995. /* write the pHYs chunk */
  996. void
  997. png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
  998.    png_uint_32 y_pixels_per_unit,
  999.    int unit_type)
  1000. {
  1001.    png_byte buf[9];
  1002.  
  1003.    png_debug(1, "in png_write_pHYs\n");
  1004.    if (unit_type >= PNG_RESOLUTION_LAST)
  1005.       png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
  1006.  
  1007.    png_save_uint_32(buf, x_pixels_per_unit);
  1008.    png_save_uint_32(buf + 4, y_pixels_per_unit);
  1009.    buf[8] = (png_byte)unit_type;
  1010.  
  1011.    png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
  1012. }
  1013. #endif
  1014.  
  1015. #if defined(PNG_WRITE_tIME_SUPPORTED)
  1016. /* write the tIME chunk.  Use either png_convert_from_struct_tm()
  1017.    or png_convert_from_time_t(), or fill in the structure yourself */
  1018. void
  1019. png_write_tIME(png_structp png_ptr, png_timep mod_time)
  1020. {
  1021.    png_byte buf[7];
  1022.  
  1023.    png_debug(1, "in png_write_tIME\n");
  1024.    if (mod_time->month  > 12 || mod_time->month  < 1 ||
  1025.        mod_time->day    > 31 || mod_time->day    < 1 ||
  1026.        mod_time->hour   > 23 || mod_time->second > 60)
  1027.    {
  1028.       png_warning(png_ptr, "Invalid time specified for tIME chunk");
  1029.       return;
  1030.    }
  1031.  
  1032.    png_save_uint_16(buf, mod_time->year);
  1033.    buf[2] = mod_time->month;
  1034.    buf[3] = mod_time->day;
  1035.    buf[4] = mod_time->hour;
  1036.    buf[5] = mod_time->minute;
  1037.    buf[6] = mod_time->second;
  1038.  
  1039.    png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
  1040. }
  1041. #endif
  1042.  
  1043. /* initializes the row writing capability of libpng */
  1044. void
  1045. png_write_start_row(png_structp png_ptr)
  1046. {
  1047.    png_size_t buf_size;
  1048.  
  1049.    png_debug(1, "in png_write_start_row\n");
  1050.    buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels *
  1051.                             png_ptr->usr_bit_depth + 7) >> 3) + 1);
  1052.  
  1053.    /* set up row buffer */
  1054.    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
  1055.    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
  1056.  
  1057.    /* set up filtering buffer, if using this filter */
  1058.    if (png_ptr->do_filter & PNG_FILTER_SUB)
  1059.    {
  1060.       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
  1061.          png_ptr->rowbytes + 1);
  1062.       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1063.    }
  1064.  
  1065.    /* We only need to keep the previous row if we are using one of these. */
  1066.    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
  1067.    {
  1068.      /* set up previous row buffer */
  1069.       png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, buf_size);
  1070.       png_memset(png_ptr->prev_row, 0, buf_size);
  1071.  
  1072.       if (png_ptr->do_filter & PNG_FILTER_UP)
  1073.       {
  1074.          png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
  1075.             png_ptr->rowbytes + 1);
  1076.          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
  1077.       }
  1078.  
  1079.       if (png_ptr->do_filter & PNG_FILTER_AVG)
  1080.       {
  1081.          png_ptr->avg_row = (png_bytep )png_malloc(png_ptr,
  1082.             png_ptr->rowbytes + 1);
  1083.          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
  1084.       }
  1085.  
  1086.       if (png_ptr->do_filter & PNG_FILTER_PAETH)
  1087.       {
  1088.          png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
  1089.             png_ptr->rowbytes + 1);
  1090.          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1091.       }
  1092.    }
  1093.  
  1094.    /* if interlaced, we need to set up width and height of pass */
  1095.    if (png_ptr->interlaced)
  1096.    {
  1097.       if (!(png_ptr->transformations & PNG_INTERLACE))
  1098.       {
  1099.          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
  1100.             png_pass_ystart[0]) / png_pass_yinc[0];
  1101.          png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
  1102.             png_pass_start[0]) / png_pass_inc[0];
  1103.       }
  1104.       else
  1105.       {
  1106.          png_ptr->num_rows = png_ptr->height;
  1107.          png_ptr->usr_width = png_ptr->width;
  1108.       }
  1109.    }
  1110.    else
  1111.    {
  1112.       png_ptr->num_rows = png_ptr->height;
  1113.       png_ptr->usr_width = png_ptr->width;
  1114.    }
  1115.    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  1116.    png_ptr->zstream.next_out = png_ptr->zbuf;
  1117. }
  1118.  
  1119. /* Internal use only.  Called when finished processing a row of data. */
  1120. void
  1121. png_write_finish_row(png_structp png_ptr)
  1122. {
  1123.    int ret;
  1124.  
  1125.    png_debug(1, "in png_write_finish_row\n");
  1126.    /* next row */
  1127.    png_ptr->row_number++;
  1128.  
  1129.    /* see if we are done */
  1130.    if (png_ptr->row_number < png_ptr->num_rows)
  1131.       return;
  1132.  
  1133.    /* if interlaced, go to next pass */
  1134.    if (png_ptr->interlaced)
  1135.    {
  1136.       png_ptr->row_number = 0;
  1137.       if (png_ptr->transformations & PNG_INTERLACE)
  1138.       {
  1139.          png_ptr->pass++;
  1140.       }
  1141.       else
  1142.       {
  1143.          /* loop until we find a non-zero width or height pass */
  1144.          do
  1145.          {
  1146.             png_ptr->pass++;
  1147.             if (png_ptr->pass >= 7)
  1148.                break;
  1149.             png_ptr->usr_width = (png_ptr->width +
  1150.                png_pass_inc[png_ptr->pass] - 1 -
  1151.                png_pass_start[png_ptr->pass]) /
  1152.                png_pass_inc[png_ptr->pass];
  1153.             png_ptr->num_rows = (png_ptr->height +
  1154.                png_pass_yinc[png_ptr->pass] - 1 -
  1155.                png_pass_ystart[png_ptr->pass]) /
  1156.                png_pass_yinc[png_ptr->pass];
  1157.             if (png_ptr->transformations & PNG_INTERLACE)
  1158.                break;
  1159.          } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
  1160.  
  1161.       }
  1162.  
  1163.       /* reset the row above the image for the next pass */
  1164.       if (png_ptr->pass < 7)
  1165.       {
  1166.          if (png_ptr->prev_row != NULL)
  1167.             png_memset(png_ptr->prev_row, 0, 
  1168.                (png_size_t) (((png_uint_32)png_ptr->usr_channels *
  1169.                (png_uint_32)png_ptr->usr_bit_depth *
  1170.                png_ptr->width + 7) >> 3) + 1);
  1171.          return;
  1172.       }
  1173.    }
  1174.  
  1175.    /* if we get here, we've just written the last row, so we need
  1176.       to flush the compressor */
  1177.    do
  1178.    {
  1179.       /* tell the compressor we are done */
  1180.       ret = deflate(&png_ptr->zstream, Z_FINISH);
  1181.       /* check for an error */
  1182.       if (ret != Z_OK && ret != Z_STREAM_END)
  1183.       {
  1184.          if (png_ptr->zstream.msg != NULL)
  1185.             png_error(png_ptr, png_ptr->zstream.msg);
  1186.          else
  1187.             png_error(png_ptr, "zlib error");
  1188.       }
  1189.       /* check to see if we need more room */
  1190.       if (!(png_ptr->zstream.avail_out) && ret == Z_OK)
  1191.       {
  1192.          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
  1193.          png_ptr->zstream.next_out = png_ptr->zbuf;
  1194.          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  1195.       }
  1196.    } while (ret != Z_STREAM_END);
  1197.  
  1198.    /* write any extra space */
  1199.    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
  1200.    {
  1201.       png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
  1202.          png_ptr->zstream.avail_out);
  1203.    }
  1204.  
  1205.    deflateReset(&png_ptr->zstream);
  1206. }
  1207.  
  1208. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  1209. /* pick out the correct pixels for the interlace pass.
  1210.  
  1211.    The basic idea here is to go through the row with a source
  1212.    pointer and a destination pointer (sp and dp), and copy the
  1213.    correct pixels for the pass.  As the row gets compacted,
  1214.    sp will always be >= dp, so we should never overwrite anything.
  1215.    See the default: case for the easiest code to understand.
  1216.    */
  1217. void
  1218. png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
  1219. {
  1220.    png_debug(1, "in png_do_write_interlace\n");
  1221.    /* we don't have to do anything on the last pass (6) */
  1222. #if defined(PNG_USELESS_TESTS_SUPPORTED)
  1223.    if (row != NULL && row_info != NULL && pass < 6)
  1224. #else
  1225.    if (pass < 6)
  1226. #endif
  1227.    {
  1228.       /* each pixel depth is handled seperately */
  1229.       switch (row_info->pixel_depth)
  1230.       {
  1231.          case 1:
  1232.          {
  1233.             png_bytep sp;
  1234.             png_bytep dp;
  1235.             int shift;
  1236.             int d;
  1237.             int value;
  1238.             png_uint_32 i;
  1239.  
  1240.             dp = row;
  1241.             d = 0;
  1242.             shift = 7;
  1243.             for (i = png_pass_start[pass]; i < row_info->width;
  1244.                i += png_pass_inc[pass])
  1245.             {
  1246.                sp = row + (png_size_t)(i >> 3);
  1247.                value = (int)(*sp >> (7 - (int)(i & 7))) & 0x1;
  1248.                d |= (value << shift);
  1249.  
  1250.                if (shift == 0)
  1251.                {
  1252.                   shift = 7;
  1253.                   *dp++ = (png_byte)d;
  1254.                   d = 0;
  1255.                }
  1256.                else
  1257.                   shift--;
  1258.  
  1259.             }
  1260.             if (shift != 7)
  1261.                *dp = (png_byte)d;
  1262.             break;
  1263.          }
  1264.          case 2:
  1265.          {
  1266.             png_bytep sp;
  1267.             png_bytep dp;
  1268.             int shift;
  1269.             int d;
  1270.             int value;
  1271.             png_uint_32 i;
  1272.  
  1273.             dp = row;
  1274.             shift = 6;
  1275.             d = 0;
  1276.             for (i = png_pass_start[pass]; i < row_info->width;
  1277.                i += png_pass_inc[pass])
  1278.             {
  1279.                sp = row + (png_size_t)(i >> 2);
  1280.                value = (*sp >> ((3 - (int)(i & 3)) << 1)) & 0x3;
  1281.                d |= (value << shift);
  1282.  
  1283.                if (shift == 0)
  1284.                {
  1285.                   shift = 6;
  1286.                   *dp++ = (png_byte)d;
  1287.                   d = 0;
  1288.                }
  1289.                else
  1290.                   shift -= 2;
  1291.             }
  1292.             if (shift != 6)
  1293.                    *dp = (png_byte)d;
  1294.             break;
  1295.          }
  1296.          case 4:
  1297.          {
  1298.             png_bytep sp;
  1299.             png_bytep dp;
  1300.             int shift;
  1301.             int d;
  1302.             int value;
  1303.             png_uint_32 i;
  1304.  
  1305.             dp = row;
  1306.             shift = 4;
  1307.             d = 0;
  1308.             for (i = png_pass_start[pass]; i < row_info->width;
  1309.                i += png_pass_inc[pass])
  1310.             {
  1311.                sp = row + (png_size_t)(i >> 1);
  1312.                value = (*sp >> ((1 - (int)(i & 1)) << 2)) & 0xf;
  1313.                d |= (value << shift);
  1314.  
  1315.                if (shift == 0)
  1316.                {
  1317.                   shift = 4;
  1318.                   *dp++ = (png_byte)d;
  1319.                   d = 0;
  1320.                }
  1321.                else
  1322.                   shift -= 4;
  1323.             }
  1324.             if (shift != 4)
  1325.                *dp = (png_byte)d;
  1326.             break;
  1327.          }
  1328.          default:
  1329.          {
  1330.             png_bytep sp;
  1331.             png_bytep dp;
  1332.             png_uint_32 i;
  1333.             png_size_t pixel_bytes;
  1334.  
  1335.             /* start at the beginning */
  1336.             dp = row;
  1337.             /* find out how many bytes each pixel takes up */
  1338.             pixel_bytes = (row_info->pixel_depth >> 3);
  1339.             /* loop through the row, only looking at the pixels that
  1340.                matter */
  1341.             for (i = png_pass_start[pass]; i < row_info->width;
  1342.                i += png_pass_inc[pass])
  1343.             {
  1344.                /* find out where the original pixel is */
  1345.                sp = row + i * pixel_bytes;
  1346.                /* move the pixel */
  1347.                if (dp != sp)
  1348.                   png_memcpy(dp, sp, pixel_bytes);
  1349.                /* next pixel */
  1350.                dp += pixel_bytes;
  1351.             }
  1352.             break;
  1353.          }
  1354.       }
  1355.       /* set new row width */
  1356.       row_info->width = (row_info->width +
  1357.          png_pass_inc[pass] - 1 -
  1358.          png_pass_start[pass]) /
  1359.          png_pass_inc[pass];
  1360.       row_info->rowbytes = ((row_info->width *
  1361.          row_info->pixel_depth + 7) >> 3);
  1362.  
  1363.    }
  1364. }
  1365. #endif
  1366.  
  1367. /* This filters the row, chooses which filter to use, if it has not already
  1368.  * been specified by the application, and then writes the row out with the
  1369.  * chosen filter. */
  1370. #define PNG_MAXSUM (~0x0UL >> 1)
  1371. #define PNG_HISHIFT 10
  1372. #define PNG_LOMASK 0xffffL
  1373. #define PNG_HIMASK (~PNG_LOMASK >> PNG_HISHIFT)
  1374. void
  1375. png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
  1376. {
  1377.    png_bytep prev_row, best_row, row_buf;
  1378.    png_uint_32 mins, bpp;
  1379.  
  1380.    png_debug(1, "in png_write_find_filter\n");
  1381.    /* find out how many bytes offset each pixel is */
  1382.    bpp = (row_info->pixel_depth + 7) / 8;
  1383.  
  1384.    prev_row = png_ptr->prev_row;
  1385.    best_row = row_buf = png_ptr->row_buf;
  1386.    mins = PNG_MAXSUM;
  1387.  
  1388.    /* The prediction method we use is to find which method provides the
  1389.     * smallest value when summing the absolute values of the distances
  1390.     * from zero using anything >= 128 as negative numbers.  This is known
  1391.     * as the "minimum sum of absolute differences" heuristic.  Other
  1392.     * heruistics are the "weighted minumum sum of absolute differences"
  1393.     * (experimental and can in theory improve compression), and the "zlib
  1394.     * predictive" method (not implemented in libpng 0.95), which does test
  1395.     * compressions of lines using different filter methods, and then chooses
  1396.     * the (series of) filter(s) which give minimum compressed data size (VERY
  1397.     * computationally expensive).
  1398.     */
  1399.  
  1400.    /* We don't need to test the 'no filter' case if this is the only filter
  1401.     * that has been chosen, as it doesn't actually do anything to the data.
  1402.     */
  1403.    if (png_ptr->do_filter & PNG_FILTER_NONE &&
  1404.        png_ptr->do_filter != PNG_FILTER_NONE)
  1405.    {
  1406.       png_bytep rp;
  1407.       png_uint_32 sum = 0;
  1408.       png_size_t i;
  1409.       int v;
  1410.  
  1411.       for (i = 0, rp = row_buf + 1; i < row_info->rowbytes; i++, rp++)
  1412.       {
  1413.          v = *rp;
  1414.          sum += (v < 128) ? v : 256 - v;
  1415.       }
  1416.  
  1417. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1418.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1419.       {
  1420.          png_uint_32 sumhi, sumlo;
  1421.          sumlo = sum & PNG_LOMASK;
  1422.          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
  1423.  
  1424.          /* Reduce the sum if we match any of the previous rows */
  1425.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1426.          {
  1427.             if (png_ptr->prev_filters[i] == PNG_FILTER_NONE)
  1428.             {
  1429.                sumlo = (sumlo * png_ptr->filter_weights[i]) >>
  1430.                   PNG_WEIGHT_SHIFT;
  1431.                sumhi = (sumhi * png_ptr->filter_weights[i]) >>
  1432.                   PNG_WEIGHT_SHIFT;
  1433.             }
  1434.          }
  1435.  
  1436.          /* Factor in the cost of this filter (this is here for completeness,
  1437.           * but it makes no sense to have a "cost" for the NONE filter, as
  1438.           * it has the minimum possible computational cost - none).
  1439.           */
  1440.          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
  1441.             PNG_COST_SHIFT;
  1442.          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
  1443.             PNG_COST_SHIFT;
  1444.  
  1445.          if (sumhi > PNG_HIMASK)
  1446.             sum = PNG_MAXSUM;
  1447.          else
  1448.             sum = (sumhi << PNG_HISHIFT) + sumlo;
  1449.       }
  1450. #endif
  1451.       mins = sum;
  1452.    }
  1453.  
  1454.    /* sub filter */
  1455.    if (png_ptr->do_filter & PNG_FILTER_SUB)
  1456.    {
  1457.       png_bytep rp, dp, lp;
  1458.       png_uint_32 sum = 0, lmins = mins;
  1459.       png_size_t i;
  1460.       int v;
  1461.  
  1462. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1463.       /* We temporarily increase the "minumum sum" by the factor we
  1464.        * would reduce the sum of this filter, so that we can do the
  1465.        * early exit comparison without scaling the sum each time.
  1466.        */
  1467.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1468.       {
  1469.          png_uint_32 lmhi, lmlo;
  1470.          lmlo = lmins & PNG_LOMASK;
  1471.          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1472.  
  1473.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1474.          {
  1475.             if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_SUB)
  1476.             {
  1477.                lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
  1478.                   PNG_WEIGHT_SHIFT;
  1479.                lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
  1480.                   PNG_WEIGHT_SHIFT;
  1481.             }
  1482.          }
  1483.  
  1484.          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1485.             PNG_COST_SHIFT;
  1486.          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1487.             PNG_COST_SHIFT;
  1488.  
  1489.          if (lmhi > PNG_HIMASK)
  1490.             lmins = PNG_MAXSUM;
  1491.          else
  1492.             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1493.       }
  1494. #endif
  1495.  
  1496.       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
  1497.            i++, rp++, dp++)
  1498.       {
  1499.          v = *dp = *rp;
  1500.  
  1501.          sum += (v < 128) ? v : 256 - v;
  1502.       }
  1503.       for (lp = row_buf + 1; i < row_info->rowbytes; i++, rp++, lp++, dp++)
  1504.       {
  1505.          v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
  1506.  
  1507.          sum += (v < 128) ? v : 256 - v;
  1508.  
  1509.          if (sum > lmins)  /* We are already worse, don't continue. */
  1510.             break;
  1511.       }
  1512.  
  1513. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1514.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1515.       {
  1516.          png_uint_32 sumhi, sumlo;
  1517.          sumlo = sum & PNG_LOMASK;
  1518.          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1519.  
  1520.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1521.          {
  1522.             if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_SUB)
  1523.             {
  1524.                sumlo = (sumlo * png_ptr->inv_filter_weights[i]) >>
  1525.                   PNG_WEIGHT_SHIFT;
  1526.                sumhi = (sumhi * png_ptr->inv_filter_weights[i]) >>
  1527.                   PNG_WEIGHT_SHIFT;
  1528.             }
  1529.          }
  1530.  
  1531.          sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1532.             PNG_COST_SHIFT;
  1533.          sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1534.             PNG_COST_SHIFT;
  1535.  
  1536.          if (sumhi > PNG_HIMASK)
  1537.             sum = PNG_MAXSUM;
  1538.          else
  1539.             sum = (sumhi << PNG_HISHIFT) + sumlo;
  1540.       }
  1541. #endif
  1542.  
  1543.       if (sum < mins)
  1544.       {
  1545.          mins = sum;
  1546.          best_row = png_ptr->sub_row;
  1547.       }
  1548.    }
  1549.  
  1550.    /* up filter */
  1551.    if (png_ptr->do_filter & PNG_FILTER_UP)
  1552.    {
  1553.       png_bytep rp, dp, pp;
  1554.       png_uint_32 sum = 0, lmins = mins;
  1555.       png_size_t i;
  1556.       int v;
  1557.  
  1558. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1559.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1560.       {
  1561.          png_uint_32 lmhi, lmlo;
  1562.          lmlo = lmins & PNG_LOMASK;
  1563.          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1564.  
  1565.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1566.          {
  1567.             if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_UP)
  1568.             {
  1569.                lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
  1570.                   PNG_WEIGHT_SHIFT;
  1571.                lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
  1572.                   PNG_WEIGHT_SHIFT;
  1573.             }
  1574.          }
  1575.  
  1576.          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
  1577.             PNG_COST_SHIFT;
  1578.          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
  1579.             PNG_COST_SHIFT;
  1580.  
  1581.          if (lmhi > PNG_HIMASK)
  1582.             lmins = PNG_MAXSUM;
  1583.          else
  1584.             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1585.       }
  1586. #endif
  1587.  
  1588.       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
  1589.            pp = prev_row + 1; i < row_info->rowbytes; i++, rp++, pp++, dp++)
  1590.       {
  1591.          v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
  1592.  
  1593.          sum += (v < 128) ? v : 256 - v;
  1594.  
  1595.          if (sum > lmins)  /* We are already worse, don't continue. */
  1596.             break;
  1597.       }
  1598.  
  1599. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1600.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1601.       {
  1602.          png_uint_32 sumhi, sumlo;
  1603.          sumlo = sum & PNG_LOMASK;
  1604.          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1605.  
  1606.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1607.          {
  1608.             if (png_ptr->prev_filters[i] == PNG_FILTER_UP)
  1609.             {
  1610.                sumlo = (sumlo * png_ptr->filter_weights[i]) >>
  1611.                   PNG_WEIGHT_SHIFT;
  1612.                sumhi = (sumhi * png_ptr->filter_weights[i]) >>
  1613.                   PNG_WEIGHT_SHIFT;
  1614.             }
  1615.          }
  1616.  
  1617.          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
  1618.             PNG_COST_SHIFT;
  1619.          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
  1620.             PNG_COST_SHIFT;
  1621.  
  1622.          if (sumhi > PNG_HIMASK)
  1623.             sum = PNG_MAXSUM;
  1624.          else
  1625.             sum = (sumhi << PNG_HISHIFT) + sumlo;
  1626.       }
  1627. #endif
  1628.  
  1629.       if (sum < mins)
  1630.       {
  1631.          mins = sum;
  1632.          best_row = png_ptr->up_row;
  1633.       }
  1634.    }
  1635.  
  1636.    /* avg filter */
  1637.    if (png_ptr->do_filter & PNG_FILTER_AVG)
  1638.    {
  1639.       png_bytep rp, dp, pp, lp;
  1640.       png_uint_32 sum = 0, lmins = mins;
  1641.       png_size_t i;
  1642.       int v;
  1643.  
  1644. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1645.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1646.       {
  1647.          png_uint_32 lmhi, lmlo;
  1648.          lmlo = lmins & PNG_LOMASK;
  1649.          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1650.  
  1651.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1652.          {
  1653.             if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_AVG)
  1654.             {
  1655.                lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
  1656.                   PNG_WEIGHT_SHIFT;
  1657.                lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
  1658.                   PNG_WEIGHT_SHIFT;
  1659.             }
  1660.          }
  1661.  
  1662.          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1663.             PNG_COST_SHIFT;
  1664.          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1665.             PNG_COST_SHIFT;
  1666.  
  1667.          if (lmhi > PNG_HIMASK)
  1668.             lmins = PNG_MAXSUM;
  1669.          else
  1670.             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1671.       }
  1672. #endif
  1673.  
  1674.       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
  1675.            pp = prev_row + 1; i < bpp; i++, rp++, pp++, dp++)
  1676.       {
  1677.          v = *dp = (png_byte)(((int)*rp - ((int)*pp / 2)) & 0xff);
  1678.  
  1679.          sum += (v < 128) ? v : 256 - v;
  1680.       }
  1681.       for (lp = row_buf + 1; i < row_info->rowbytes;
  1682.            i++, rp++, pp++, lp++, dp++)
  1683.       {
  1684.          v = *dp = (png_byte)(((int)*rp - (((int)*pp + (int)*lp) / 2)) & 0xff);
  1685.  
  1686.          sum += (v < 128) ? v : 256 - v;
  1687.  
  1688.          if (sum > lmins)  /* We are already worse, don't continue. */
  1689.             break;
  1690.       }
  1691.  
  1692. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1693.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1694.       {
  1695.          png_uint_32 sumhi, sumlo;
  1696.          sumlo = sum & PNG_LOMASK;
  1697.          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1698.  
  1699.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1700.          {
  1701.             if (png_ptr->prev_filters[i] == PNG_FILTER_NONE)
  1702.             {
  1703.                sumlo = (sumlo * png_ptr->filter_weights[i]) >>
  1704.                   PNG_WEIGHT_SHIFT;
  1705.                sumhi = (sumhi * png_ptr->filter_weights[i]) >>
  1706.                   PNG_WEIGHT_SHIFT;
  1707.             }
  1708.          }
  1709.  
  1710.          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1711.             PNG_COST_SHIFT;
  1712.          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1713.             PNG_COST_SHIFT;
  1714.  
  1715.          if (sumhi > PNG_HIMASK)
  1716.             sum = PNG_MAXSUM;
  1717.          else
  1718.             sum = (sumhi << PNG_HISHIFT) + sumlo;
  1719.       }
  1720. #endif
  1721.  
  1722.       if (sum < mins)
  1723.       {
  1724.          mins = sum;
  1725.          best_row = png_ptr->avg_row;
  1726.       }
  1727.    }
  1728.  
  1729.    /* Paeth filter */
  1730.    if (png_ptr->do_filter & PNG_FILTER_PAETH)
  1731.    {
  1732.       png_bytep rp, dp, pp, cp, lp;
  1733.       png_uint_32 sum = 0, lmins = mins;
  1734.       png_size_t i;
  1735.       int v;
  1736.  
  1737. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1738.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1739.       {
  1740.          png_uint_32 lmhi, lmlo;
  1741.          lmlo = lmins & PNG_LOMASK;
  1742.          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1743.  
  1744.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1745.          {
  1746.             if (png_ptr->prev_filters[i] == PNG_FILTER_VALUE_PAETH)
  1747.             {
  1748.                lmlo = (lmlo * png_ptr->inv_filter_weights[i]) >>
  1749.                   PNG_WEIGHT_SHIFT;
  1750.                lmhi = (lmhi * png_ptr->inv_filter_weights[i]) >>
  1751.                   PNG_WEIGHT_SHIFT;
  1752.             }
  1753.          }
  1754.  
  1755.          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1756.             PNG_COST_SHIFT;
  1757.          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1758.             PNG_COST_SHIFT;
  1759.  
  1760.          if (lmhi > PNG_HIMASK)
  1761.             lmins = PNG_MAXSUM;
  1762.          else
  1763.             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1764.       }
  1765. #endif
  1766.  
  1767.       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
  1768.            pp = prev_row + 1; i < bpp; i++, rp++, pp++, dp++)
  1769.       {
  1770.          v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
  1771.  
  1772.          sum += (v < 128) ? v : 256 - v;
  1773.       }
  1774.       for (lp = row_buf + 1, cp = prev_row + 1; i < row_info->rowbytes;
  1775.            i++, rp++, pp++, lp++, dp++, cp++)
  1776.       {
  1777.          int a, b, c, pa, pb, pc, p;
  1778.  
  1779.          b = *pp;
  1780.          c = *cp;
  1781.          a = *lp;
  1782.  
  1783.          p = a + b - c;
  1784.          pa = abs(p - a);
  1785.          pb = abs(p - b);
  1786.          pc = abs(p - c);
  1787.  
  1788.          if (pa <= pb && pa <= pc)
  1789.             p = a;
  1790.          else if (pb <= pc)
  1791.             p = b;
  1792.          else
  1793.             p = c;
  1794.  
  1795.          v = *dp = (png_byte)(((int)*rp - p) & 0xff);
  1796.  
  1797.          sum += (v < 128) ? v : 256 - v;
  1798.  
  1799.          if (sum > lmins)  /* We are already worse, don't continue. */
  1800.             break;
  1801.       }
  1802.  
  1803. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1804.       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1805.       {
  1806.          png_uint_32 sumhi, sumlo;
  1807.          sumlo = sum & PNG_LOMASK;
  1808.          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1809.  
  1810.          for (i = 0; i < png_ptr->num_prev_filters; i++)
  1811.          {
  1812.             if (png_ptr->prev_filters[i] == PNG_FILTER_PAETH)
  1813.             {
  1814.                sumlo = (sumlo * png_ptr->filter_weights[i]) >>
  1815.                   PNG_WEIGHT_SHIFT;
  1816.                sumhi = (sumhi * png_ptr->filter_weights[i]) >>
  1817.                   PNG_WEIGHT_SHIFT;
  1818.             }
  1819.          }
  1820.  
  1821.          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1822.             PNG_COST_SHIFT;
  1823.          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1824.             PNG_COST_SHIFT;
  1825.  
  1826.          if (sumhi > PNG_HIMASK)
  1827.             sum = PNG_MAXSUM;
  1828.          else
  1829.             sum = (sumhi << PNG_HISHIFT) + sumlo;
  1830.       }
  1831. #endif
  1832.  
  1833.       if (sum < mins)
  1834.       {
  1835.          best_row = png_ptr->paeth_row;
  1836.       }
  1837.    }
  1838.  
  1839.    /* Do the actual writing of the filtered row data from the chosen filter. */
  1840.    png_write_filtered_row(png_ptr, best_row);
  1841.  
  1842. #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  1843.    /* Save the type of filter we picked this time for future calculations */
  1844.    if (png_ptr->num_prev_filters > 0)
  1845.    {
  1846.       png_byte i;
  1847.  
  1848.       for (i = 1; i < png_ptr->num_prev_filters; i++)
  1849.       {
  1850.          png_ptr->prev_filters[i] = png_ptr->prev_filters[i - 1];
  1851.       }
  1852.       png_ptr->prev_filters[i] = best_row[0];
  1853.    }
  1854. #endif
  1855. }
  1856.  
  1857.  
  1858. /* Do the actual writing of a previously filtered row. */
  1859. void
  1860. png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
  1861. {
  1862.    png_debug(1, "in png_write_filtered_row\n");
  1863.    png_debug1(2, "filter = %d\n", filtered_row[0]);
  1864.    /* set up the zlib input buffer */
  1865.    png_ptr->zstream.next_in = filtered_row;
  1866.    png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
  1867.    /* repeat until we have compressed all the data */
  1868.    do
  1869.    {
  1870.       int ret; /* return of zlib */
  1871.  
  1872.       /* compress the data */
  1873.       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
  1874.       /* check for compression errors */
  1875.       if (ret != Z_OK)
  1876.       {
  1877.          if (png_ptr->zstream.msg != NULL)
  1878.             png_error(png_ptr, png_ptr->zstream.msg);
  1879.          else
  1880.             png_error(png_ptr, "zlib error");
  1881.       }
  1882.  
  1883.       /* see if it is time to write another IDAT */
  1884.       if (!(png_ptr->zstream.avail_out))
  1885.       {
  1886.          /* write the IDAT and reset the zlib output buffer */
  1887.          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
  1888.          png_ptr->zstream.next_out = png_ptr->zbuf;
  1889.          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  1890.       }
  1891.    /* repeat until all data has been compressed */
  1892.    } while (png_ptr->zstream.avail_in);
  1893.  
  1894.    /* swap the current and previous rows */
  1895.    if (png_ptr->prev_row != NULL)
  1896.    {
  1897.       png_bytep tptr;
  1898.  
  1899.       tptr = png_ptr->prev_row;
  1900.       png_ptr->prev_row = png_ptr->row_buf;
  1901.       png_ptr->row_buf = tptr;
  1902.    }
  1903.  
  1904.    /* finish row - updates counters and flushes zlib if last row */
  1905.    png_write_finish_row(png_ptr);
  1906.  
  1907. #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  1908.    png_ptr->flush_rows++;
  1909.  
  1910.    if (png_ptr->flush_dist > 0 &&
  1911.        png_ptr->flush_rows >= png_ptr->flush_dist)
  1912.    {
  1913.       png_write_flush(png_ptr);
  1914.    }
  1915. #endif /* PNG_WRITE_FLUSH_SUPPORTED */
  1916. }
  1917.  
  1918.